﻿// 文件路径: ViewModels/NavRoomViewModel.cs
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using CommunityToolkit.Mvvm.ComponentModel; // 确保引用基类
using CommunityToolkit.Mvvm.Input;
using RevitProject.SpaceManager.Core; // 使用 NavRoomService
using RevitProject.SpaceManager.Models;
using RevitProject.SpaceManager.ViewModel.DialogViewModelPart;
using RevitProject.SpaceManager.ViewModel.NavRoomVmPart;
using RevitProject.SpaceManager.Views;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input; // 需要 ICommand
using System.Collections.Specialized; 
using System.ComponentModel;
namespace RevitProject.SpaceManager.ViewModel.NavRoomVmPart
{
    /// <summary>
    /// 新的 NavRoomView.xaml 的主 ViewModel。
    /// 使用手动属性实现 INotifyPropertyChanged。
    /// </summary>
    public class NavRoomViewModel : ObservableObject // 移除 partial
    {
        #region 私有字段 Private Fields

        private readonly NavRoomService _navRoomService;
        private readonly UIApplication _uiApp;

        private List<RoomDataModel> _allRoomData = new List<RoomDataModel>();
        private List<LevelInfoModel> _allLevels = new List<LevelInfoModel>();

        private bool _isLoading;
        private ObservableCollection<LevelTreeNodeViewModel> _levelTreeNodes = new ObservableCollection<LevelTreeNodeViewModel>();
        private LevelTreeNodeViewModel _selectedLevelNode;
        private ObservableCollection<RoomItemViewModel> _filteredRoomList = new ObservableCollection<RoomItemViewModel>();
        private int _filteredRoomCount;
        private ObservableCollection<string> _availableZones = new ObservableCollection<string>();
        private string _selectedZone = "全部分区";
        private string _roomFilterText = string.Empty;
        private ObservableCollection<string> _visibleRoomColumns = new ObservableCollection<string>();
        private ObservableCollection<string> _availableCategories = new ObservableCollection<string>();


        #endregion

        #region 公共属性 Public Properties

        /// <summary>
        /// 指示是否正在加载数据。
        /// </summary>
        public bool IsLoading
        {
            get => _isLoading;
            set => SetProperty(ref _isLoading, value);
        }

        /// <summary>
        /// 用于楼层树视图的节点集合。
        /// </summary>
        public ObservableCollection<LevelTreeNodeViewModel> LevelTreeNodes
        {
            get => _levelTreeNodes;
            private set => SetProperty(ref _levelTreeNodes, value); // 通常只在内部设置
        }

        /// <summary>
        /// 当前在楼层树中选中的节点。
        /// </summary>
        public LevelTreeNodeViewModel SelectedLevelNode
        {
            get => _selectedLevelNode;
            set
            {
                if (SetProperty(ref _selectedLevelNode, value))
                {
                    UpdateRoomList(); // 选中项改变时更新房间列表
                }
            }
        }

        /// <summary>
        /// 经过筛选后在 DataGrid 中显示的房间行项目 ViewModel 集合。
        /// </summary>
        public ObservableCollection<RoomItemViewModel> FilteredRoomList => _filteredRoomList; // 直接返回 backing field


        /// <summary>
        /// 筛选后的房间数量。
        /// </summary>
        public int FilteredRoomCount { get; private set; }

        /// <summary>
        /// 可供选择的分区列表。
        /// </summary>
        public ObservableCollection<string> AvailableZones
        {
            get => _availableZones;
            private set => SetProperty(ref _availableZones, value); // 内部设置
        }

        /// <summary>
        /// 当前选中的分区筛选条件。
        /// </summary>
        public string SelectedZone
        {
            get => _selectedZone;
            set
            {
                if (SetProperty(ref _selectedZone, value))
                {
                    UpdateRoomList(); // 选中项改变时更新房间列表
                }
            }
        }

        /// <summary>
        /// 用于筛选房间名称或编号的文本。
        /// </summary>
        public string RoomFilterText
        {
            get => _roomFilterText;
            set
            {
                if (SetProperty(ref _roomFilterText, value))
                {
                    UpdateRoomList(); // 文本改变时更新房间列表
                }
            }
        }

        /// <summary>
        /// 当前可见的 DataGrid 列的属性名称集合。
        /// </summary>
        public ObservableCollection<string> VisibleRoomColumns => _visibleRoomColumns;

        /// <summary>
        /// 可供选择的房间类别列表（用于右键菜单）。
        /// </summary>
        public ObservableCollection<string> AvailableCategories
        {
            get => _availableCategories;
            private set => SetProperty(ref _availableCategories, value); // 内部设置
        }

        #endregion

        #region 列管理字典 Column Management Dictionary

        // 列管理字典 (Key: RoomItemViewModel 属性名, Value: 显示名)
        // 保持 internal readonly
        public readonly Dictionary<string, string> AllAvailableRoomColumns = new Dictionary<string, string>
        {
             { nameof(RoomItemViewModel.RoomNumber), "编号" },
             { nameof(RoomItemViewModel.RoomName), "名称" },
             { nameof(RoomItemViewModel.FormattedArea), "面积(㎡)" },
             { nameof(RoomItemViewModel.CategoryName), "类别" },
             { nameof(RoomItemViewModel.LevelName), "楼层" },
             { nameof(RoomItemViewModel.LevelElevation), "标高(mm)" },
             { nameof(RoomItemViewModel.Department), "部门" },
             { nameof(RoomItemViewModel.Occupancy), "占用" },
             { nameof(RoomItemViewModel.Comments), "注释" },
             { nameof(RoomItemViewModel.ZoneName), "分区" },
             // 在此添加 RoomItemViewModel 中的所有其他可选列
        };

        #endregion

        #region 命令 Commands

        public IAsyncRelayCommand LoadDataCommand { get; }
        public IAsyncRelayCommand AssignCategoryCommand { get; }
       
        public ICommand SelectAllRoomsCommand { get; }
        public ICommand DeselectAllRoomsCommand { get; }
        public ICommand UpdateSelectedLevelNodeCommand { get; }
        #endregion

        #region 构造函数 Constructor

        /// <summary>
        /// 初始化 NavRoomViewModel。
        /// </summary>
        public NavRoomViewModel(UIApplication uiApp, NavRoomService navRoomService)
        {
            _uiApp = uiApp;
            _navRoomService = navRoomService;

            // 初始化默认可见列
            _visibleRoomColumns = new ObservableCollection<string> // 直接初始化 backing field
            {
                nameof(RoomItemViewModel.RoomNumber),
                nameof(RoomItemViewModel.RoomName),
                nameof(RoomItemViewModel.FormattedArea),
                nameof(RoomItemViewModel.CategoryName),
                nameof(RoomItemViewModel.LevelName),
                nameof(RoomItemViewModel.ZoneName)
            };

            _filteredRoomList.CollectionChanged += FilteredRoomList_CollectionChanged; // 监听集合变化
            // 初始化命令
            LoadDataCommand = new AsyncRelayCommand(InitializeAsync);
            AssignCategoryCommand = new AsyncRelayCommand<string>(ExecuteAssignCategoryAsync, CanExecuteAssignCategory);
            
            SelectAllRoomsCommand = new RelayCommand(ExecuteSelectAllRooms, CanExecuteSelectAll);
            DeselectAllRoomsCommand = new RelayCommand(ExecuteDeselectAllRooms, CanExecuteDeselectAll);

            UpdateSelectedLevelNodeCommand = new RelayCommand<object>(selectedItem =>
            {
                if (selectedItem is LevelTreeNodeViewModel node)
                {
                    SelectedLevelNode = node; // 直接设置属性，会触发 OnSelectedLevelNodeChanged -> UpdateRoomList
                }
                
            });
        }

        #endregion

        #region 命令执行方法 Command Methods

        /// <summary>
        /// 异步初始化加载数据。
        /// </summary>
        private async Task InitializeAsync()
        {
            // 防止重复加载
            if (IsLoading) return;
            IsLoading = true;
            Debug.WriteLine("NavRoomViewModel: 初始化数据 (确保首次加载显示)...");

            // 清空旧数据，确保刷新效果
            LevelTreeNodes.Clear();
            

            try
            {
                List<LevelInfoModel> levels = null;
                List<RoomDataModel> roomData = null;
                List<string> zones = null;
                List<string> categories = null;

                // 在后台线程加载数据
                await Task.Run(() =>
                {
                    levels = _navRoomService.GetLevels();
                    roomData = _navRoomService.GetAllRoomDataModels();
                    zones = _navRoomService.GetDistinctZones(roomData);
                    categories = _navRoomService.GetAvailableCategories();
                });

                // --- 在 UI 线程更新集合 ---
                _allLevels = levels;
                _allRoomData = roomData;

                // 构建楼层树 ViewModel (这部分可以在 UI 线程，因为它创建 ViewModel 对象)
                BuildLevelTree(); // 填充 LevelTreeNodes

                // 更新下拉框数据源
                var zonesCollection = new ObservableCollection<string> { "全部分区" };
                zones.ForEach(z => zonesCollection.Add(z));
                AvailableZones = zonesCollection;
                // SelectedZone 保持其当前值或默认值 "全部分区"

                var categoriesCollection = new ObservableCollection<string>();
                categories.ForEach(c => categoriesCollection.Add(c));
                AvailableCategories = categoriesCollection;

                // 设置默认选中的楼层节点 (Setter 会触发第一次 UpdateRoomList)
                var firstNode = LevelTreeNodes.FirstOrDefault();
                SelectedLevelNode = firstNode;


                Debug.WriteLine($"NavRoomViewModel: 初始化/刷新完成。楼层: {_allLevels.Count}, 房间: {_allRoomData.Count}, 显示房间: {FilteredRoomCount}");
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"NavRoomViewModel 初始化/刷新时发生错误: {ex.ToString()}");
                await Application.Current.Dispatcher.InvokeAsync(() =>
                    MessageBox.Show($"加载房间数据时出错: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error)
                );
            }
            finally
            {
                IsLoading = false;
            }
        }

        /// <summary>
        /// 监听 FilteredRoomList 变化以更新计数
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void FilteredRoomList_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            // 更新计数，并通知 UI
            FilteredRoomCount = _filteredRoomList.Count;
            OnPropertyChanged(nameof(FilteredRoomCount)); // 手动触发计数属性的变更通知
            // 同时更新依赖选择的命令状态
            NotifySelectionCommandsChanged();
        }

        /// <summary>
        /// 构建楼层树的 ViewModel 节点。
        /// </summary>
        private void BuildLevelTree()
        {
            var tree = new ObservableCollection<LevelTreeNodeViewModel>();
            if (_allLevels == null || _allRoomData == null)
            {
                LevelTreeNodes = tree; // 更新为空树
                return;
            }

            // 创建 RoomItemViewModel 实例
            var roomVMs = _allRoomData.Select(data => new RoomItemViewModel(data)).ToList();
            // 按 LevelId 分组
            var roomVMsByLevel = roomVMs.GroupBy(vm => vm.LevelId)
                                       .ToDictionary(g => g.Key, g => g.AsEnumerable());

            foreach (var levelInfo in _allLevels)
            {
                roomVMsByLevel.TryGetValue(levelInfo.Id, out var roomsOnThisLevel);
                var levelNode = new LevelTreeNodeViewModel(levelInfo, roomsOnThisLevel ?? Enumerable.Empty<RoomItemViewModel>());
                tree.Add(levelNode);
            }
            LevelTreeNodes = tree; // 使用 Setter 更新属性并触发通知
        }

        /// <summary>
        /// 更新右侧 DataGrid 的房间列表。
        /// </summary>
        private void UpdateRoomList()
        {
            if (SelectedLevelNode == null)
            {
                // 如果没有选中楼层，清空列表
                if (_filteredRoomList.Any()) // 只有列表非空时才清空，避免不必要的通知
                {
                    _filteredRoomList.Clear(); // 会触发 CollectionChanged -> 更新 Count
                    Debug.WriteLine("NavRoomViewModel: UpdateRoomList - 无选中楼层，列表已清空。");
                }
                return;
            }

            Debug.WriteLine($"NavRoomViewModel: 更新房间列表。楼层: {SelectedLevelNode.DisplayName}, 分区: {SelectedZone}, 筛选: '{RoomFilterText}'");

            // 1. 执行筛选逻辑，得到目标 RoomItemViewModel 列表 (IEnumerable<RoomItemViewModel>)
            var roomsToDisplayQuery = SelectedLevelNode.AssociatedRoomVMs.AsEnumerable();
            if (_selectedZone != "全部分区")
            {
                roomsToDisplayQuery = roomsToDisplayQuery.Where(vm => vm.ZoneName.Equals(_selectedZone, StringComparison.OrdinalIgnoreCase));
            }
            string filterText = _roomFilterText?.Trim();
            if (!string.IsNullOrWhiteSpace(filterText))
            {
                roomsToDisplayQuery = roomsToDisplayQuery.Where(vm =>
                    (vm.RoomName != null && vm.RoomName.IndexOf(filterText, StringComparison.OrdinalIgnoreCase) >= 0) ||
                    (vm.RoomNumber != null && vm.RoomNumber.IndexOf(filterText, StringComparison.OrdinalIgnoreCase) >= 0));
            }
            // 将查询结果排序并物化为列表
            var finalRoomsToShow = roomsToDisplayQuery.OrderBy(vm => vm.RoomNumber).ToList();

            // 2. --- 优化：比较新旧列表内容，仅在必要时更新集合 ---
            //    这可以避免不必要的 Clear 和 AddRange 操作，减少 UI 刷新。
            bool areEqual = _filteredRoomList.SequenceEqual(finalRoomsToShow);

            if (!areEqual)
            {
                Debug.WriteLine($"NavRoomViewModel: 检测到列表内容变化 (旧: {_filteredRoomList.Count}, 新: {finalRoomsToShow.Count})。正在更新集合...");
                // 3. 更新现有集合 _filteredRoomList 的内容
                //    先 Clear，再 AddRange 是比较高效的方式更新 ObservableCollection
                _filteredRoomList.Clear(); // 清空现有集合 (会触发 CollectionChanged)
                foreach (var roomVM in finalRoomsToShow)
                {
                    _filteredRoomList.Add(roomVM); // 逐个添加 (也会触发 CollectionChanged)
                }
                // 注意：上面 Clear+Add 会触发多次 CollectionChanged。如果性能有问题，
                // 可以考虑创建自定义的 ObservableRangeCollection 或使用其他库提供的支持 Range 操作的集合。
                // 但对于一般情况，Clear+Add 是可接受的。

                // FilteredRoomCount 会通过 CollectionChanged 事件自动更新
                Debug.WriteLine($"NavRoomViewModel: 集合更新完成。FilteredRoomCount = {FilteredRoomCount}");
            }
            else
            {
                Debug.WriteLine("NavRoomViewModel: 列表内容未变化，跳过集合更新。");
            }

        }

        // --- 列设置命令 ---
        
        // --- 分类指派命令 ---
        private bool CanExecuteAssignCategory(string targetCategoryName)
        {
            return !string.IsNullOrEmpty(targetCategoryName) &&
                   _filteredRoomList != null && // 使用 backing field
                   _filteredRoomList.Any(vm => vm.IsSelected);
        }

        private async Task ExecuteAssignCategoryAsync(string targetCategoryName)
        {
            if (!CanExecuteAssignCategory(targetCategoryName)) return;

            var selectedVMs = _filteredRoomList.Where(vm => vm.IsSelected).ToList(); // 使用 backing field
            var roomIdsToUpdate = selectedVMs.Select(vm => vm.RoomId).ToList();
            int count = selectedVMs.Count;

            // 确认对话框（需要在 UI 线程）
            MessageBoxResult confirmResult = MessageBoxResult.None;
            await Application.Current.Dispatcher.InvokeAsync(() =>
            {
                confirmResult = MessageBox.Show($"确定要将选中的 {count} 个房间的类别设置为“{targetCategoryName}”吗？", "确认归类", MessageBoxButton.YesNo, MessageBoxImage.Question);
            });

            if (confirmResult != MessageBoxResult.Yes) return;

            IsLoading = true; // Setter 触发通知
            bool success = false;
            try
            {
                success = await _navRoomService.AssignCategoryToRoomsAsync(roomIdsToUpdate, targetCategoryName);
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"NavRoomViewModel AssignCategory Error: {ex.ToString()}");
                success = false;
                // 考虑在 UI 线程显示错误
                await Application.Current.Dispatcher.InvokeAsync(() =>
                   MessageBox.Show($"分配类别时发生错误: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error)
                );
            }
            finally
            {
                IsLoading = false; // Setter 触发通知
            }


            if (success)
            {
                // 在 UI 线程更新 ViewModel 属性
                await Application.Current.Dispatcher.InvokeAsync(() =>
                {
                    foreach (var vm in selectedVMs)
                    {
                        vm.CategoryName = targetCategoryName; // 直接更新 ViewModel 属性 (Setter 触发通知)
                    }
                    MessageBox.Show($"成功将 {count} 个房间的类别更新为“{targetCategoryName}”。", "操作完成", MessageBoxButton.OK, MessageBoxImage.Information);
                });
            }
            else
            {
                // Service 层或上面的 Catch 块应该已经提示了错误
                // await Application.Current.Dispatcher.InvokeAsync(() =>
                //    MessageBox.Show($"未能更新房间类别。", "操作失败", MessageBoxButton.OK, MessageBoxImage.Warning)
                // );
            }
            NotifySelectionCommandsChanged(); // 更新命令状态
        }

        // --- 全选/全不选命令 ---
        private bool CanExecuteSelectAll() => _filteredRoomList != null && _filteredRoomList.Any(vm => !vm.IsSelected);
        private void ExecuteSelectAllRooms()
        {
            if (_filteredRoomList == null) return;
            foreach (var vm in _filteredRoomList) vm.IsSelected = true; // Setter 触发通知
            NotifySelectionCommandsChanged();
        }

        private bool CanExecuteDeselectAll() => _filteredRoomList != null && _filteredRoomList.Any(vm => vm.IsSelected);
        private void ExecuteDeselectAllRooms()
        {
            if (_filteredRoomList == null) return;
            foreach (var vm in _filteredRoomList) vm.IsSelected = false; // Setter 触发通知
            NotifySelectionCommandsChanged();
        }

        /// <summary>
        /// 通知依赖于选择状态的命令更新其 CanExecute 状态。
        /// </summary>
        private void NotifySelectionCommandsChanged()
        {
            (SelectAllRoomsCommand as RelayCommand)?.NotifyCanExecuteChanged();
            (DeselectAllRoomsCommand as RelayCommand)?.NotifyCanExecuteChanged();
            (AssignCategoryCommand as AsyncRelayCommand<string>)?.NotifyCanExecuteChanged();
        }

        /// <summary>
        /// 获取当前活动窗口。
        /// </summary>
        private Window GetActiveWindow()
        {
            // 这个方法依赖于 Application.Current，需要在 UI 线程调用或确保其可用
            return Application.Current?.Windows.OfType<Window>().SingleOrDefault(x => x.IsActive && x is SpaceManagerView);
        }

        #endregion
    }
}